package com.hs.srm.base.common.utils;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import javax.annotation.PostConstruct;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import sunnykid.Sunnykid;
import sunnykid.util.ClassUtils;
import sunnykid.util.UtilException;

import com.hs.srm.base.common.annotation.AddressMapping;
import com.hs.srm.base.common.base.CloneableEntity;
import com.hs.srm.base.modules.sys.entity.SysAreasEntity;
import com.hs.srm.base.modules.sys.entity.SysCitiesEntity;
import com.hs.srm.base.modules.sys.entity.SysCountriesEntity;
import com.hs.srm.base.modules.sys.entity.SysProvincesEntity;
import com.hs.srm.base.modules.sys.service.SysAreasService;
import com.hs.srm.base.modules.sys.service.SysCitiesService;
import com.hs.srm.base.modules.sys.service.SysCountriesService;
import com.hs.srm.base.modules.sys.service.SysProvincesService;

/**
 * 
 * <p>標題：字典表数据工具类</p>
 * <p>描述：字典表数据工具类</p>
 * <p>版權：版權所有 (c) 2019</p>
 * <p>組織：厚声集团</p>
 *
 * @author 鐘曉籟
 * @version V1.0.0
 * @date 2019年1月21日 上午11:05:27
 * @since V1.0.0
 */
@Component
public class AddressDataUtil {

	/**
	 * 省、市、区三种类型的枚举
	 */
	public static enum AddressType {
		COUNTRY, PROVINCE, CITY, AREA;
	}

	@Autowired
	private SysCountriesService sysCountriesService;

	@Autowired
	private SysProvincesService sysProvincesService;

	@Autowired
	private SysCitiesService sysCitiesService;

	@Autowired
	private SysAreasService sysAreasService;

	private static SysCountriesService sysCountriesServiceObj;
	private static SysProvincesService sysProvincesServiceObj;
	private static SysCitiesService sysCitiesServiceObj;
	private static SysAreasService sysAreasServiceObj;

	@PostConstruct
	public void init() {
		AddressDataUtil.sysCountriesServiceObj = this.sysCountriesService;
		AddressDataUtil.sysProvincesServiceObj = this.sysProvincesService;
		AddressDataUtil.sysCitiesServiceObj = this.sysCitiesService;
		AddressDataUtil.sysAreasServiceObj = this.sysAreasService;
	}

	private static List<SysCountriesEntity> countriesList = null;// 国家表数据缓存
	private static List<SysProvincesEntity> provincesList = null;// 省份表数据缓存
	private static List<SysCitiesEntity> citiesList = null;// 城市表数据缓存
	private static List<SysAreasEntity> areasList = null;// 区县表数据缓存

	/**
	 * 获取所有国家信息
	 * @return List<SysCountriesEntity>
	 */
	public static List<SysCountriesEntity> getCountries() {
		if(countriesList != null) {
			return countriesList;
		}
		synchronized(AddressDataUtil.class) {
			countriesList = sysCountriesServiceObj.selectList(null);
			return countriesList;
		}
	}

	/**
	 * 获取所有省份信息
	 * @return List<SysProvincesEntity>
	 */
	public static List<SysProvincesEntity> getProvinces() {
		if(provincesList != null) {
			return provincesList;
		}
		synchronized(AddressDataUtil.class) {
			provincesList = sysProvincesServiceObj.selectList(null);
			return provincesList;
		}
	}

	/**
	 * 获取所有城市信息
	 * @return List<SysCitiesEntity>
	 */
	public static List<SysCitiesEntity> getCities() {
		if(citiesList != null) {
			return citiesList;
		}
		synchronized(AddressDataUtil.class) {
			citiesList = sysCitiesServiceObj.selectList(null);
			return citiesList;
		}
	}

	/**
	 * 获取所有区县信息
	 * @return List<SysAreasEntity>
	 */
	public static List<SysAreasEntity> getAreas() {
		if(areasList != null) {
			return areasList;
		}
		synchronized(AddressDataUtil.class) {
			areasList = sysAreasServiceObj.selectList(null);
			return areasList;
		}
	}

	/**
	 * 根据省查询市
	 * @param provinceCode
	 * @return
	 */
	public static List<SysCitiesEntity> getCitiesByProvince(String provinceCode) {
		List<SysCitiesEntity> allCities = AddressDataUtil.getCities();
		List<SysCitiesEntity> citiesInProvince = new ArrayList<SysCitiesEntity>();
		for(SysCitiesEntity c : allCities) {
			if(c.getProvinceCode().equals(provinceCode)) {
				citiesInProvince.add(c);
			}
		}
		return citiesInProvince;
	}

	/**
	 * 根据市询区
	 * @param cityCode
	 * @return
	 */
	public static List<SysAreasEntity> getAreasByCity(String cityCode) {
		List<SysAreasEntity> allAreas = AddressDataUtil.getAreas();
		List<SysAreasEntity> areasInCity = new ArrayList<SysAreasEntity>();
		for(SysAreasEntity a : allAreas) {
			if(a.getCityCode().equals(cityCode)) {
				areasInCity.add(a);
			}
		}
		return areasInCity;
	}

	/**
	 * 省市区根据code查询name
	 * @param code
	 * @param addressType
	 * @return
	 */
	public static String getNameByCode(String code, AddressType addressType) {
		switch(addressType) {
			case COUNTRY:
				List<SysCountriesEntity> cylist = AddressDataUtil.getCountries();
				for(SysCountriesEntity spe : cylist) {
					if(spe.getShortName() != null && spe.getShortName().equals(code)) {
						return spe.getChsName();
					}
				}
				break;
			case PROVINCE:
				List<SysProvincesEntity> plist = AddressDataUtil.getProvinces();
				for(SysProvincesEntity spe : plist) {
					if(spe.getProvinceCode().equals(code)) {
						return spe.getProvince();
					}
				}
				break;
			case CITY:
				List<SysCitiesEntity> clist = AddressDataUtil.getCities();
				for(SysCitiesEntity sce : clist) {
					if(sce.getCityCode().equals(code)) {
						return sce.getCity();
					}
				}
				break;
			case AREA:
				List<SysAreasEntity> alist = AddressDataUtil.getAreas();
				for(SysAreasEntity sae : alist) {
					if(sae.getAreaCode().equals(code)) {
						return sae.getArea();
					}
				}
				break;
			default:
				return null;
		}
		return null;
	}

	/**
	 * 省市区根据name查询code
	 * @param name
	 * @param addressType
	 * @return
	 */
	public static String getCodeByName(String name, AddressType addressType) {
		switch(addressType) {
			case COUNTRY:
				List<SysCountriesEntity> cylist = AddressDataUtil.getCountries();
				for(SysCountriesEntity spe : cylist) {
					if(spe.getChsName() != null && spe.getChsName().equals(name)) {
						return spe.getShortName();
					}
				}
				break;
			case PROVINCE:
				List<SysProvincesEntity> plist = AddressDataUtil.getProvinces();
				for(SysProvincesEntity spe : plist) {
					if(spe.getProvince().equals(name)) {
						return spe.getProvinceCode();
					}
				}
				break;
			case CITY:
				List<SysCitiesEntity> clist = AddressDataUtil.getCities();
				for(SysCitiesEntity sce : clist) {
					if(sce.getCity().equals(name)) {
						return sce.getCityCode();
					}
				}
				break;
			case AREA:
				List<SysAreasEntity> alist = AddressDataUtil.getAreas();
				for(SysAreasEntity sae : alist) {
					if(sae.getArea().equals(name)) {
						return sae.getAreaCode();
					}
				}
				break;
			default:
				return null;
		}
		return null;
	}

	/**
	 * 将对象中的省市区的编码转为文字
	 * @param t
	 * @return
	 * @throws UtilException
	 */
	public static <T extends CloneableEntity<?>> T parseToAddressText(T t) throws UtilException {
		if(t == null) {
			return null;
		}
		T cloneT = Sunnykid.clone(t);
		Set<Field> fieldSet = ClassUtils.getAllFields(cloneT.getClass());
		for(Field field : fieldSet) {
			AddressMapping addressMapping = field.getAnnotation(AddressMapping.class);
			if(addressMapping != null) {
				Object val = ClassUtils.getFieldValue(cloneT, field);
				if(val != null) {
					String vn = AddressDataUtil.getNameByCode(val.toString(), addressMapping.type());
					ClassUtils.setFieldValue(cloneT, field, vn);
				}
			}
		}
		return cloneT;
	}

	/**
	 * 将对象中的省市区的文字转为编码
	 * @param t
	 * @return
	 * @throws UtilException
	 */
	public static <T extends CloneableEntity<?>> T parseToAddressCode(T t) throws UtilException {
		if(t == null) {
			return null;
		}
		T cloneT = Sunnykid.clone(t);
		Set<Field> fieldSet = ClassUtils.getAllFields(cloneT.getClass());
		for(Field field : fieldSet) {
			AddressMapping addressMapping = field.getAnnotation(AddressMapping.class);
			if(addressMapping != null) {
				Object vn = ClassUtils.getFieldValue(cloneT, field);
				if(vn != null) {
					String val = AddressDataUtil.getCodeByName(vn.toString(), addressMapping.type());
					ClassUtils.setFieldValue(cloneT, field, val);
				}
			}
		}
		return cloneT;
	}

}
